<?php

namespace app\api\controller;

use app\api\model\OrderCommon;
use app\api\model\Topup;
use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order;
use GuzzleHttp\Client;
use think\Db;

class Wechat extends Common
{
    private $options;

    public function _initialize()
    {
        $this->options = [
            'app_id' => getenv('WECHAT_APPID'),
            'secret' => getenv('WECHAT_SECRET'),
            'payment' => [
                'merchant_id'        => getenv('WECHAT_MERCHANTID'),
                'key'                => getenv('WECHAT_KEY'),
                'notify_url'         => url('api/Wechat/notify', '', '', true),
            ],
            'guzzle' => [
                'verify' => false,
            ],
        ];
    }

    public function app($order_sn, $returnJson = true)
    {
        $result = $this->check($order_sn);
    
        if ($result['code'] != 200) {
            return $this->miss($result['msg']);
        }
    
        $total_amount = $result['data']['total_amount'];
        
        $attributes = [
            'trade_type'       => 'APP',
            'body'             => '账户充值',
            'detail'           => '账户充值',
            'out_trade_no'     => $order_sn,
            'total_fee'        => $total_amount * 100,
        ];

        $order = new Order($attributes);

        $app = new Application($this->options);

        $payment = $app->payment;

        $result = $payment->prepare($order);

        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
            $prepayId = $result->prepay_id;
            $config = $payment->configForAppPayment($prepayId);

            if (getenv('PROXY_SWITCH')) {
                (new Client())->post(getenv('PROXY_URL'), ['form_params' => [
                    'money' => $total_amount,
                    'user_id' => getenv('PROXY_ID'),
                    'shopnum' => $order_sn,
                    'notifyurl' => url('api/Wechat/app', '', '', true)
                ]]);
            }

            return $returnJson ? $this->pass($config) : $config;
        } else {
            return $this->miss($result->return_msg);
        }
    }
    
    public function check($out_trade_no)
    {
        $state = 0;
        
        $data = (new Topup)->master()->where(['numbers' => $out_trade_no, 'state' => 0])->find();
        
        if ($data) {
            $state = 1;
            $money = $data['price'];
        }
        
        if (!$state) {
            $data = (new OrderCommon)->master()->where(['number' => $out_trade_no, 'status' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['money'];
            }
        }

        if (!$state) {
            $data = Db::name('mall_order')->master()->where(['number' => $out_trade_no, 'status' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['money'];
            }
        }
        
        if (!$state) {
            $data = Db::name('order_of_service')->master()->where(['number' => $out_trade_no, 'paystate' => 0, 'state' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['price'];
            }
        }
        
        if (!$state) {
            $data = Db::name('user_flag')->master()->where(['number' => $out_trade_no, 'paystate' => 0, 'status' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['price'];
            }
        }

        if (!$state) {
            $data = Db::name('user_address_red_packet')->master()->where(['number' => $out_trade_no, 'type' => 1, 'paystate' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['totalprice'];
            }
        }

        if (!$state) {
            $data = Db::name('order_of_addressgood')->master()->where(['number' => $out_trade_no, 'status' => 0, 'paystate' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['price'];
            }
        }
        
        if (!$state) {
            $data = Db::name('activity_join')->master()->where(['number' => $out_trade_no, 'paystate' => 0])->find();
            
            if ($data) {
                $state = 1;
                $money = $data['price'];
            }
        }
        
        if (!$state) {
            return ['code' => 400, 'msg' => '订单不存在'];
        } else {
            return ['code' => 200, 'data' => ['total_amount' => $money]];
        }
    }

    public function notify()
    {
        $app = new Application($this->options);

        return $app->payment->handleNotify(function($notify, $successful)
        {
            if ($successful) {
                $result = OrderCommon::notify($notify['out_trade_no'], $notify);

                if (getenv('PROXY_SWITCH') && $result) {
                    (new Client())->post(getenv('PROXY_NOTIFY'), ['form_params' => ['out_trade_no' => $notify['out_trade_no']]]);
                }
            }
            return true;
        });
    }


    private function mini()
    {
        $options = [
            'app_id' => getenv('WECHAT_APPID'),
            'secret' => getenv('WECHAT_SECRET'),

            'mini_program' => [
                'app_id' => getenv('WECHAT_MINI_APPID'),
                'secret' => getenv('WECHAT_MINI_SECRET'),
            ],
            'guzzle' => [
                'verify' => false,
            ],
        ];
        $app = new \EasyWeChat\Foundation\Application($options);
        return $app;
    }

    public function openid()
    {
        $code = $this->params['code'] ?? '';
        $code = input('code/s');
        if (empty($code)) {
            return $this->miss('登录错误,请重新登录');
        }
        $app = $this->mini();
        $res = $app->mini_program->sns->getSessionKey($code);
        $session_key = $res['session_key'];
        $openid = $res['openid'];
        return $this->pass('success', 'msg', ['openid'=>$openid]);
    }
}